import { createRef, useMemo } from 'react'
import { Result } from 'ahooks/lib/useRequest/src/types'
import dayjs from 'dayjs'
import { Button, DatePicker, Form, Input, InputNumber, Popover, Radio, Select } from 'antd'
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'

import { AgGridReact, CusAgGrid } from '@/components/CusAgGrid'
import { addAGCellTexty } from '@oBiz/components/addTexty'
import { TAddressListRes } from '@oBiz/hooks/SWRApi/useAddressList'
import { getTransportationTypeName } from '@oBiz/TrackManage/Detail/utils'
import { IWaybillRecordItemWithIndex, TCellParams } from '@oBiz/TrackManage/List/interface'
import { useBoundStore } from '@oBiz/TrackManage/List/store'
import { getLogisticsProductServiceLevelName, getTailLineName } from '@oBiz/TrackManage/List/utils'
import { TOperationType } from '../interface'
import { getTableColumnDefs } from './config'
import styles from './styles.module.less'

// 通用跨字段差值校验：当前值与另一个字段值的差值不能超过 limit
const diffWithinLimit =
  (
    getFieldValue: (namePath: (string | number)[]) => any,
    key: number,
    otherField: 'logisticsChannelServiceTransitMin' | 'logisticsChannelServiceTransitMax',
    limit = 20,
    message = '最短与最长时效差值不能超过20',
  ) =>
  async (_: any, val: any) => {
    const other = getFieldValue(['content', key, otherField])
    if (val === undefined || val === null || other === undefined || other === null) return Promise.resolve()
    const curNum = Number(val)
    const otherNum = Number(other)
    if (!Number.isFinite(curNum) || !Number.isFinite(otherNum)) return Promise.resolve()
    if (Math.abs(otherNum - curNum) > limit) return Promise.reject(message)
    return Promise.resolve()
  }

const Cell = (p: TCellParams, addressList: Result<TAddressListRes, []>) => {
  const { field } = p.colDef || {}
  const key = Number(p.node.rowIndex)
  const optionsAddress = addressList?.data?.list?.map(item => ({
    label: item?.chineseName,
    value: item?.addressId,
  }))
  switch (field) {
    case 'waybillNo': {
      return (
        <Form.Item noStyle name={['content', key, 'waybillNo']} initialValue={p.value}>
          {p.value as string}
        </Form.Item>
      )
    }
    case 'logisticsChannelServiceLevel': {
      return (
        <Form.Item
          noStyle
          name={['content', key, 'logisticsChannelServiceLevel']}
          rules={[{ required: true, message: '请选择服务等级' }]}
        >
          <Radio.Group
            options={getLogisticsProductServiceLevelName.valueList.map(item => ({
              label: getLogisticsProductServiceLevelName(item),
              value: item,
            }))}
            block
            buttonStyle="solid"
            optionType="button"
            size="small"
          />
        </Form.Item>
      )
    }
    case 'logisticsChannelServiceTransitMin': {
      return (
        <Form.Item
          noStyle
          shouldUpdate={(values, prevValues) =>
            (values as any)?.['content']?.[key]?.logisticsChannelServiceTransitMax !==
            (prevValues as any)?.['content']?.[key]?.logisticsChannelServiceTransitMax
          }
        >
          {({ getFieldValue }) => (
            <Form.Item
              noStyle
              name={['content', key, 'logisticsChannelServiceTransitMin']}
              rules={[
                { required: true, message: '请输入最短时效' },
                { validator: diffWithinLimit(getFieldValue, key, 'logisticsChannelServiceTransitMax') },
              ]}
            >
              <InputNumber style={{ width: '100%' }} placeholder="请输入最短时效" />
            </Form.Item>
          )}
        </Form.Item>
      )
    }
    case 'logisticsChannelServiceTransitMax': {
      return (
        <Form.Item
          noStyle
          shouldUpdate={(values, prevValues) =>
            (values as any)?.['content']?.[key]?.logisticsChannelServiceTransitMin !==
            (prevValues as any)?.['content']?.[key]?.logisticsChannelServiceTransitMin
          }
        >
          {({ getFieldValue }) => (
            <Form.Item
              noStyle
              name={['content', key, 'logisticsChannelServiceTransitMax']}
              rules={[
                { required: true, message: '请输入最长时效' },
                { validator: diffWithinLimit(getFieldValue, key, 'logisticsChannelServiceTransitMin') },
              ]}
            >
              <InputNumber style={{ width: '100%' }} placeholder="请输入最长时效" />
            </Form.Item>
          )}
        </Form.Item>
      )
    }
    case 'transportType': {
      return getTransportationTypeName(p.value as number)
    }
    case 'carrier': {
      return (
        <Form.Item noStyle name={['content', key, 'carrier']} rules={[{ required: true, message: '请输入承运商' }]}>
          <Input placeholder="请输入承运商" />
        </Form.Item>
      )
    }
    case 'vesselName': {
      return (
        <Form.Item noStyle name={['content', key, 'vesselName']} rules={[{ required: true, message: '请输入船名' }]}>
          <Input placeholder="请输入船名" maxLength={50} />
        </Form.Item>
      )
    }
    case 'voyageNumber': {
      return (
        <Form.Item noStyle name={['content', key, 'voyageNumber']} rules={[{ required: true, message: '请输入航次' }]}>
          <Input placeholder="请输入航次" maxLength={50} />
        </Form.Item>
      )
    }
    case 'containerNumber': {
      return (
        <Form.Item
          noStyle
          name={['content', key, 'containerNumber']}
          rules={[{ required: true, message: '请输入柜号' }]}
        >
          <Input placeholder="请输入柜号" maxLength={30} />
        </Form.Item>
      )
    }
    case 'departureLocationId': {
      return (
        <>
          <Form.Item
            noStyle
            name={['content', key, 'departureLocationId']}
            rules={[{ required: true, message: '请输入起运港' }]}
          >
            <Select placeholder="请选择起运港" maxLength={50} style={{ width: '100%' }} options={optionsAddress} />
          </Form.Item>
          <Form.Item noStyle name={['content', key, 'departureLocationName']} />
        </>
      )
    }
    case 'etd': {
      return (
        <Form.Item noStyle name={['content', key, 'etd']} rules={[{ required: true, message: '请输入 etd' }]}>
          <DatePicker style={{ width: '100%' }} />
        </Form.Item>
      )
    }
    case 'destinationLocationId': {
      return (
        <>
          <Form.Item
            noStyle
            name={['content', key, 'destinationLocationId']}
            rules={[{ required: true, message: '请输入目的港' }]}
          >
            <Select placeholder="请选择目的港" style={{ width: '100%' }} options={optionsAddress} />
          </Form.Item>
          <Form.Item noStyle name={['content', key, 'destinationLocationName']} />
        </>
      )
    }
    case 'eta': {
      return (
        <Form.Item
          noStyle
          shouldUpdate={(values, prevValues) =>
            (values as any)?.['content']?.[key]?.etd !== (prevValues as any)?.['content']?.[key]?.etd
          }
        >
          <Form.Item noStyle name={['content', key, 'eta']} rules={[{ required: true, message: '请输入 eta' }]}>
            <DatePicker style={{ width: '100%' }} />
          </Form.Item>
        </Form.Item>
      )
    }
    case 'transitDays': {
      return (
        <Form.Item
          noStyle
          shouldUpdate={(values, prevValues) =>
            values['content'][key].eta !== prevValues['content'][key].eta ||
            values['content'][key].etd !== prevValues['content'][key].etd
          }
        >
          {({ getFieldValue }) => {
            const etd = getFieldValue(['content', key, 'etd'])
            const eta = getFieldValue(['content', key, 'eta'])
            if (!etd || !eta) return ''
            return dayjs().diff(etd, 'day') - dayjs().diff(eta, 'day')
          }}
        </Form.Item>
      )
    }
    case 'lastMileTransportType': {
      return (
        <Form.Item
          noStyle
          name={['content', key, 'lastMileTransportType']}
          rules={[{ required: true, message: '请选择尾程运输方式' }]}
        >
          <Select
            style={{ width: '100%' }}
            placeholder="请选择尾程运输方式"
            options={getTailLineName.valueList.map(item => ({
              label: getTailLineName(item),
              value: item,
            }))}
          />
        </Form.Item>
      )
    }
    case 'lastMileCarrier': {
      return (
        <Form.Item
          noStyle
          shouldUpdate={(values, prevValues) =>
            values['content'][key].lastMileTransportType !== prevValues['content'][key].lastMileTransportType
          }
        >
          {({ getFieldValue }) => {
            const lastMileTransportType = getFieldValue(['content', key, 'lastMileTransportType'])
            return (
              <Form.Item
                name={['content', key, 'lastMileCarrier']}
                rules={[{ required: true, message: '请输入尾程服务商' }]}
                noStyle
              >
                {lastMileTransportType === 1 ? (
                  <Select
                    style={{ width: '100%' }}
                    allowClear
                    placeholder="请选择尾程服务商"
                    options={['UPS', 'FedEx', 'DHL', 'USPS等'].map(item => ({
                      label: item,
                      value: item,
                    }))}
                  />
                ) : (
                  <Input
                    style={{ width: '100%' }}
                    placeholder="请输入尾程服务商"
                    disabled={lastMileTransportType === 3}
                  />
                )}
              </Form.Item>
            )
          }}
        </Form.Item>
      )
    }
    case 'lastMileWaybillNo': {
      return (
        <Form.Item noStyle name={['content', key, 'lastMileWaybillNo']}>
          <Input placeholder="请输入尾程 BOL" />
        </Form.Item>
      )
    }
    case 'result': {
      return p.value === undefined ? (
        ''
      ) : (
        <Popover content={p.value === 1 ? '成功' : `${p.value}`}>
          <Button
            type="text"
            icon={
              p.value === 1 ? (
                <CheckCircleOutlined style={{ color: 'green' }} />
              ) : (
                <CloseCircleOutlined style={{ color: 'red' }} />
              )
            }
          >
            {p.value === 1 ? '成功' : '失败'}
          </Button>
        </Popover>
      )
    }
    default: {
      return addAGCellTexty(p)
    }
  }
}

export const BatchUpdateTable = ({
  operationType,
  addressList,
}: {
  operationType: TOperationType
  addressList: Result<TAddressListRes, []>
}) => {
  const waybillList = useBoundStore(state => state.waybillList)
  const tableRef = createRef<AgGridReact<IWaybillRecordItemWithIndex>>()

  const columnDefs = useMemo(() => getTableColumnDefs(operationType), [operationType])

  const rowData = useMemo(() => {
    if (operationType === 'updateFirstLine') {
      return waybillList.filter(item => item.transportType === 1)
    }
    return waybillList ?? []
  }, [operationType, waybillList])

  return (
    <div className={styles.batchUpdateTable}>
      <CusAgGrid<IWaybillRecordItemWithIndex>
        ref={tableRef}
        rowData={rowData}
        loading={false}
        columnDefs={columnDefs}
        cellSelection={false}
        suppressCellFocus
        suppressColumnVirtualisation
        defaultColDef={{ sortable: false, cellRenderer: (p: TCellParams) => Cell(p, addressList) }}
      />
    </div>
  )
}
